﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;
using System.Web.Configuration;
using System.Configuration;
using IntroduceCompany.Singleton;
using IntroduceCompany.Util;
using IntroduceCompany.DTO;
using System.Data.Linq;

namespace IntroduceCompany.Models
{

    public class Admin_Validation
    {

        //[System.ComponentModel.DataAnnotations.MetadataType(typeof(IntroduceCompany.Models.Admin_Validation))]

        [Required(ErrorMessage = "Tên đăng nhập phải có")]
        [RegularExpression(ConstantClass.testMemberNameRegular_1, ErrorMessage = "Tên đăng nhập từ 6 đến 20 ký tự. Vd: abc_01.11-dd")]
        public string UserName { get; set; }

        [Required(ErrorMessage = "Họ tên admin phải có")]
        public string FullName { get; set; }

        [RegularExpression(ConstantClass.testDate_1, ErrorMessage = "Sai định dạng ngày. Ngày sinh có dạng dd/mm/yyyy")]
        public string Birthday { get; set; }

        [RegularExpression(ConstantClass.testEmailRegular_1, ErrorMessage = "Không đúng định dạng email.")]
        public string Email { get; set; }

        [RegularExpression(ConstantClass.testPhoneRegular_1, ErrorMessage = "Không đúng định dạng điện thoại.\n Vd: ## or +##.## or #.##.## or +##.## or ## ##.## or (##) ##.##")]
        public string Phone { get; set; }

    }

    public class LogOnAdminModel
    {
        [Required]
        [DisplayName("Tài khoản")]
        public string UserName { get; set; }

        [Required]
        [DataType(DataType.Password)]
        [DisplayName("Mật khẩu")]
        public string Password { get; set; }

        [DisplayName("Nhớ ?")]
        public bool RememberMe { get; set; }
    }


    #region IFormsAuthenticationService

    public interface IFormsAuthenticationService
    {
        void SignIn(string userName, bool createPersistentCookie);
        void SignOut();
    }

    public class FormsAuthenticationService : IFormsAuthenticationService
    {
        public void SignIn(string userName, bool createPersistentCookie)
        {
            if (String.IsNullOrEmpty(userName)) throw new ArgumentException("Value cannot be null or empty.", "userName");
            //////////
            var roles = new List<string> { };
            string tempRole = DataSingleton.GetAdminModels().GetAdminRole(userName);
            roles.Add(tempRole);
            //if (tempRole.Equals("C"))
            //{
            //    roles.Add("Manager");
            //}
            //else if (tempRole.Equals("B"))
            //{
            //    roles.Add("Leader");
            //}
          //  SetAuthenticationCookie(userName, role); use for one user has one role
            SetAuthenticationCookie(userName, roles, createPersistentCookie);
            
            //// original code
            //   FormsAuthentication.SetAuthCookie(userName, createPersistentCookie); 
        }

        //Create an encrypted FormsAuthenticationTicket and store the user roles
        //in pipe delimited format as part of the userData
        //Send down to client in a cookie
        //This will be read back in global.asax
        private void SetAuthenticationCookie(string userName, List<string> roles, bool createPersistentCookie)
        {
            HttpCookiesSection cookieSection = (HttpCookiesSection)ConfigurationManager.GetSection("system.web/httpCookies");
            AuthenticationSection authenticationSection = (AuthenticationSection)ConfigurationManager.GetSection("system.web/authentication");

            FormsAuthenticationTicket authTicket =
                new FormsAuthenticationTicket(
                1, userName.ToString(), DateTime.Now, DateTime.Now.AddMinutes(authenticationSection.Forms.Timeout.TotalMinutes),
                createPersistentCookie, string.Join("|", roles.ToArray()));

            String encryptedTicket = FormsAuthentication.Encrypt(authTicket);
            HttpCookie authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);

            if (cookieSection.RequireSSL || authenticationSection.Forms.RequireSSL)
            {
                authCookie.Secure = true;
            }

            HttpContext.Current.Response.Cookies.Add(authCookie);
        }


        public void SignOut()
        {
            FormsAuthentication.SignOut();
            
        }
    }

    #endregion

////////////////////////////////////////////////////////////////////////////////////
  
    #region IMembershipService

    public interface IMembershipService
    {
        bool ValidateUser(string userName, string password);
    }

    public class AccountMembershipService : IMembershipService
    {
        private readonly MembershipProvider _provider;

        public AccountMembershipService()
            : this(null)
        {
        }

        public AccountMembershipService(MembershipProvider provider)
        {
            _provider = provider ?? Membership.Provider;
        }

        public bool ValidateUser(string userName, string password)
        {
            if (String.IsNullOrEmpty(userName)) throw new ArgumentException("Value cannot be null or empty.", "userName");
            if (String.IsNullOrEmpty(password)) throw new ArgumentException("Value cannot be null or empty.", "password");

            return _provider.ValidateUser(userName, password);
        }
    }

    #endregion



    public class AdminModels
    {
        /// <summary>
        /// Get all admin and sort by adminID decrease
        /// </summary>
        /// <returns></returns>
        internal IQueryable<AdminListView> GetAdminList(bool IsSuperAdmin)
        {
            if (IsSuperAdmin) //Get List of all Admin.
            {
                return (DataSingleton.GetInstance().AdminListViews.OrderByDescending(admin => admin.AdminID));
            }
            else //Get List of all Admin expect 
            {
                return (DataSingleton.GetInstance().AdminListViews.Where(admin => admin.AdminID != 1).OrderByDescending(admin => admin.AdminID));
            }
            
        }

        /// <summary>
        /// Set a admin is visible or not
        /// </summary>
        /// <param name="adminID"></param>
        /// <param name="visible"></param>
        internal void ChangeAdminVisible(int adminID, bool visible)
        {
            Administrator tempAdmin = DataSingleton.GetInstance().Administrators.SingleOrDefault(admin => admin.AdminID == adminID);
            tempAdmin.Visible = !visible;

            DataSingleton.GetInstance().Administrators.Context.SubmitChanges();
        }

        /// <summary>
        /// Insert new Admin into database
        /// </summary>
        /// <param name="admin"></param>
        /// <returns></returns>
        internal String CreateAdmin(Administrator admin)
        {
            string pass = "";
            try
            {
                Administrator tempAdmin = new Administrator();
                tempAdmin.RoleID = admin.RoleID;
                tempAdmin.UserName = admin.UserName;

                pass = RandomPassword.Generate(ConstantClass._randomPassLength);
                tempAdmin.Pass = GeneralClass.GetMD5Hash(pass);

                tempAdmin.FullName = admin.FullName;
                tempAdmin.GenderID = admin.GenderID;
                tempAdmin.Birthday = admin.Birthday;
                tempAdmin.Address = admin.Address;
                tempAdmin.Email = admin.Email;
                tempAdmin.Phone = admin.Phone;
                tempAdmin.Createdate = DateTime.Now;
                tempAdmin.Visible = true;
                tempAdmin.LoginDate = DateTime.Now;
                tempAdmin.LogoutDate = DateTime.Now;


                DataSingleton.GetInstance().Administrators.InsertOnSubmit(tempAdmin);
                DataSingleton.GetInstance().Administrators.Context.SubmitChanges();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            return pass;
        }


        /// <summary>
        /// Check Username is existed or not. True is existed and otherwise
        /// </summary>
        /// <param name="p"></param>
        /// <returns></returns>
        internal bool CheckUserNameIsExisted(String username)
        {
            return DataSingleton.GetInstance().Administrators.Any(admin => admin.UserName == username);
        }


        internal AdminListView GetOneAdmin(string username, string password)
        {
            return DataSingleton.GetInstance().AdminListViews.SingleOrDefault(u => u.UserName == username && u.Pass == password);
        }

        internal string GetAdminRole(string userName)
        {
            return DataSingleton.GetInstance().Administrators.SingleOrDefault(u => u.UserName == userName).RoleID.ToString();
        }


        /// <summary>
        /// Check user and pass is correct or not
        /// </summary>
        /// <param name="username"></param>
        /// <param name="password"></param>
        /// <returns></returns>
        internal bool CheckUserAvailability(string username, string password)
        {
            return DataSingleton.GetInstance().AdminListViews.Any(u => u.UserName == username && u.Pass == password && u.Visible == true);
        }


        /// <summary>
        /// Get a admin filter by adminID
        /// </summary>
        /// <param name="adminID"></param>
        /// <returns></returns>
        internal Administrator GetOneAdminEdit(int adminID)
        {
            return DataSingleton.GetInstance().Administrators.SingleOrDefault(admin => admin.AdminID == adminID);
        }

        /// <summary>
        /// Get a admin filter by username
        /// </summary>
        /// <param name="adminID"></param>
        /// <returns></returns>
        internal Administrator GetOneAdminEdit(String username)
        {
            return DataSingleton.GetInstance().Administrators.SingleOrDefault(admin => admin.UserName == username);
        }


        /// <summary>
        /// Change information of admin
        /// </summary>
        /// <param name="admin"></param>
        /// <returns></returns>
        internal bool EditAdmin(Administrator admin)
        {
            try
            {
                //General_dto.ClearCacheDataContext(DataSingleton.GetInstance());
                //DataSingleton.GetInstance().Administrators.Attach(admin, true);
                //DataSingleton.GetInstance().Refresh(RefreshMode.KeepCurrentValues, admin);
                //DataSingleton.GetInstance().Administrators.Context.SubmitChanges();

                Administrator tempAdmin = DataSingleton.GetInstance().Administrators.SingleOrDefault(ad => ad.AdminID == admin.AdminID);
                tempAdmin.RoleID = admin.RoleID;
                tempAdmin.UserName = admin.UserName;
                tempAdmin.FullName = admin.FullName;
                tempAdmin.GenderID = admin.GenderID;
                tempAdmin.Birthday = admin.Birthday;
                tempAdmin.Address = admin.Address;
                tempAdmin.Email = admin.Email;
                tempAdmin.Phone = admin.Phone;
                tempAdmin.Createdate = DateTime.Now;

                DataSingleton.GetInstance().Administrators.Context.SubmitChanges();
                //DataSingleton.GetInstance().Refresh(RefreshMode.KeepChanges, tempAdmin);

            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                return false;
            }
            return true;
        }



        /// <summary>
        /// Change information of admin and password
        /// </summary>
        /// <param name="admin"></param>
        /// <returns></returns>
        internal bool EditAdminAndChangePass(Administrator admin, String newPass)
        {
            try
            {

                Administrator tempAdmin = DataSingleton.GetInstance().Administrators.SingleOrDefault(ad => ad.AdminID == admin.AdminID);
                //tempAdmin.UserName = tempAdmin.UserName;
                tempAdmin.FullName = admin.FullName;
                tempAdmin.GenderID = admin.GenderID;
                tempAdmin.Birthday = admin.Birthday;
                tempAdmin.Address = admin.Address;
                tempAdmin.Email = admin.Email;
                tempAdmin.Phone = admin.Phone;
                tempAdmin.Createdate = DateTime.Now;
                if (newPass != "")
                {
                    tempAdmin.Pass = GeneralClass.GetMD5Hash(newPass);
                }

                DataSingleton.GetInstance().Administrators.Context.SubmitChanges();

            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                return false;
            }
            return true;
        }


        /// <summary>
        /// Reset Password and random new password
        /// </summary>
        /// <param name="p"></param>
        /// <returns></returns>
        internal string ResetPassword(int adminID)
        {
            string pass = "";
            try
            {
                Administrator tempAdmin = DataSingleton.GetInstance().Administrators.SingleOrDefault(admin => admin.AdminID == adminID);

                pass = RandomPassword.Generate(ConstantClass._randomPassLength);
                tempAdmin.Pass = GeneralClass.GetMD5Hash(pass);
                tempAdmin.Createdate = DateTime.Now;

                DataSingleton.GetInstance().Administrators.Context.SubmitChanges();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            return pass;
        }


        /// <summary>
        /// Check Username and Password is correct or not. True is correct
        /// </summary>
        /// <param name="username"></param>
        /// <param name="currentPass"></param>
        /// <returns></returns>
        internal bool CheckUsernameAndPassIsCorrect(String username, String currentPass)
        {
            return DataSingleton.GetInstance().Administrators.Any(admin => admin.UserName == username && admin.Pass == GeneralClass.GetMD5Hash(currentPass));
        }

        internal void UpdateLogInTime(String username)
        {
            Administrator admin = DataSingleton.GetInstance().Administrators.SingleOrDefault(u=>u.UserName == username);
            admin.LoginDate = DateTime.Now;
            DataSingleton.GetInstance().Administrators.Context.SubmitChanges();
        }

        internal void UpdateLogOutTime(String username)
        {
            Administrator admin = DataSingleton.GetInstance().Administrators.SingleOrDefault(u => u.UserName == username);
            admin.LogoutDate = DateTime.Now;
            DataSingleton.GetInstance().Administrators.Context.SubmitChanges();
        }
    }
}